package com.xnyzc.lhy.order.service.impl.auth;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xnyzc.lhy.common.component.config.security.JwtTokenUtil;
import com.xnyzc.lhy.common.component.config.security.TokenUser;
import com.xnyzc.lhy.common.constant.CommonConstant;
import com.xnyzc.lhy.common.entity.ParameterEnum;
import com.xnyzc.lhy.common.entity.Qw;
import com.xnyzc.lhy.common.entity.Rv;
import com.xnyzc.lhy.common.exception.PangException;
import com.xnyzc.lhy.common.penum.EErrorCode;
import com.xnyzc.lhy.common.penum.ELoginUserType;
import com.xnyzc.lhy.common.penum.auth.OaAuthEnum;
import com.xnyzc.lhy.common.util.*;
import com.xnyzc.lhy.mis.entity.sidebar.OaSysOffice;
import com.xnyzc.lhy.order.entity.cms.OaSysRole;
import com.xnyzc.lhy.order.entity.common.order.OrderCommon;
import com.xnyzc.lhy.order.entity.driver.wallet.OaDWallet;
import com.xnyzc.lhy.order.entity.param.auth.DetectionToken;
import com.xnyzc.lhy.order.entity.param.auth.LoginToken;
import com.xnyzc.lhy.order.entity.result.user.UserLoginResult;
import com.xnyzc.lhy.order.entity.sidebar.OaCUserOffice;
import com.xnyzc.lhy.order.entity.sms.OaSmsCodeRecord;
import com.xnyzc.lhy.order.entity.sms.OaSmsErrorCode;
import com.xnyzc.lhy.order.entity.system.OaSysUser;
import com.xnyzc.lhy.order.entity.system.OaSysUserRole;
import com.xnyzc.lhy.order.entity.user.FeedBack;
import com.xnyzc.lhy.order.entity.user.OaCUser;
import com.xnyzc.lhy.order.entity.user.OaDUser;
import com.xnyzc.lhy.order.entity.user.OaDUserInfo;
import com.xnyzc.lhy.order.entity.user.wallet.OaCWallet;
import com.xnyzc.lhy.order.entity.vehicle.OaDDriverVehicle;
import com.xnyzc.lhy.order.entity.vehicle.OaSysVehicle;
import com.xnyzc.lhy.order.feign.amap.IAmapService;
import com.xnyzc.lhy.order.feign.heli.IUserToHeLiService;
import com.xnyzc.lhy.order.feign.push.FeignMessageSendService;
import com.xnyzc.lhy.order.mapper.cms.OaSysRoleMapper;
import com.xnyzc.lhy.order.mapper.driver.wallet.OaDWalletMapper;
import com.xnyzc.lhy.order.mapper.sidebar.OaCUserOfficeMapper;
import com.xnyzc.lhy.order.mapper.sidebar.OaSysOfficeMapper;
import com.xnyzc.lhy.order.mapper.system.OaSysUserMapper;
import com.xnyzc.lhy.order.mapper.system.OaSysUserRoleMapper;
import com.xnyzc.lhy.order.mapper.user.FeedBackMapper;
import com.xnyzc.lhy.order.mapper.user.OaCUserMapper;
import com.xnyzc.lhy.order.mapper.user.OaDUserInfoMapper;
import com.xnyzc.lhy.order.mapper.user.OaDUserMapper;
import com.xnyzc.lhy.order.mapper.user.wallet.OaCWalletMapper;
import com.xnyzc.lhy.order.mapper.vehicle.OaDDriverVehicleMapper;
import com.xnyzc.lhy.order.mapper.vehicle.OaSysVehicleMapper;
import com.xnyzc.lhy.order.service.auth.IOaAuthService;
import com.xnyzc.lhy.order.service.cms.util.IOfficeUtilService;
import com.xnyzc.lhy.order.service.sms.IOaSmsCodeRecordService;
import com.xnyzc.lhy.order.service.sms.IOaSmsErrorCodeService;
import com.xnyzc.lhy.order.service.user.IOaCUserService;
import com.xnyzc.lhy.order.service.user.IOaDUserService;
import com.xnyzc.lhy.resource.entity.worksheet.param.heli.LoginSynchronousParam;
import com.xnyzc.lhy.resource.entity.worksheet.param.heli.RoleSynchronousParam;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.time.LocalDate;
import java.util.*;

/**
 * <p>
 * 用户登录认证相关 服务实现类
 * </p>
 *
 * @author liuju
 * @since 2019-07-22
 */
@Slf4j
@Service
public class OaAuthServiceImpl implements IOaAuthService {

    @Value("${global.whitelist.oaCUserPhone}")
    private String whitelistOaCUserPhone;

    @Value("${global.whitelist.oaDUserPhone}")
    private String whitelistOaDUserPhone;

    @Autowired
    RedisTemplate redisTemplate;

    @Autowired
    private OaCUserMapper oaCUserMapper;
    @Autowired
    IOaSmsErrorCodeService iOaSmsErrorCodeService;

    @Autowired
    IOaSmsCodeRecordService iOaSmsCodeRecordService;

    @Autowired
    IOaCUserService IOaCUserService;

    @Autowired
    IOaDUserService IOaDUserService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private OaCWalletMapper oaCWalletMapper;

    @Autowired
    private OaCUserOfficeMapper oaCUserOfficeMapper;

    @Autowired
    private OaSysUserMapper oaSysUserMapper;

    @Autowired
    private OaSysUserRoleMapper oaSysUserRoleMapper;

    @Autowired
    private OaSysRoleMapper oaSysRoleMapper;

    @Autowired
    private OaSysOfficeMapper oaSysOfficeMapper;

    @Autowired
    private OaDWalletMapper oaDWalletMapper;

    @Autowired
    private IOfficeUtilService iOfficeUtilService;

    @Autowired
    private OaDUserInfoMapper oaDUserInfoMapper;

    @Autowired
    private OaSysVehicleMapper oaSysVehicleMapper;

    @Autowired
    private OaDDriverVehicleMapper oaDDriverVehicleMapper;

    @Autowired
    private OaDUserMapper oaDUserMapper;

    @Autowired
    private FeignMessageSendService feignMessageSendService;

    @Autowired
    private IUserToHeLiService userToHeLiService;

    @Autowired
    private OaDUserInfoMapper dUserInfoMapper;

    @Autowired
    private OrderCommon orderCommon;

    @Autowired
    private IAmapService amapService;

    @Autowired
    private OaCUserMapper userMapper;

    @Autowired
    private FeedBackMapper feedBackMapper;

    public static String serviceId;

    @Value("${global.amap.lyServiceId}")
    public void setServiceId(String amapServiceId) {
        serviceId = amapServiceId;
    }

    /**
     * 乘客端登录
     *
     * @param loginToken
     * @return
     */
    @Override
    public String getLoginTokenByC(LoginToken loginToken) {

        String phone = loginToken.getSourceId();
        String credentials = loginToken.getCredentials();
        String tag = TokenUtil.getTag();
        String userType = TokenUtil.getUserType();
        TokenUser tokenUser = new TokenUser();
        Date date = new Date();
        String token = "";
        BigDecimal bigDecimal = new BigDecimal(BigInteger.ZERO);
        // 验证码登录
        if (Objects.equals(loginToken.getScope(), OaAuthEnum.smsType.getValue())) {
            // 验证验证码是否正确
            checkSmsCode(userType, phone, credentials, tag, whitelistOaCUserPhone);
            // 判断用户是否存在，不存在则注册
            OaCUser userOaCUser = checkCUserExist(phone, tag);

            // 注册用户
            if (CheckUtil.objIsEmpty(userOaCUser)) {

                // 屏蔽登录 modify by jon 2020.4.17
                //throw new PangException(EErrorCode.unRegisterError);

                Long id = IDUtil.nextId();
                OaCUser oaCUser = new OaCUser();
                oaCUser.setUserPhone(phone);
                oaCUser.setTag(tag);
                oaCUser.setUserId(id);
                oaCUser.setUserToken(token);
                oaCUser.setCreateTime(date);
                oaCUser.setCreateUser(id);
                oaCUser.setUpdateTime(date);
                oaCUser.setUpdateUser(id);
                oaCUser.setUserToken(null);
                // 设置用户信息
                UserLoginResult userLoginResult = new UserLoginResult();
                addUserOfficeInfo(oaCUser, userLoginResult);
                tokenUser.setUser(userLoginResult);
                tokenUser.setLoginUserType(ELoginUserType.c);
                tokenUser.setClientId(TokenUtil.getClientId());
                //tokenUser.setTokenUserId(userOaCUser.getUserId());
                tokenUser.setTokenUserId(id);
                //生成token
                token = jwtTokenUtil.generateToken(tokenUser);
                oaCUser.setUserToken(token);
                IOaCUserService.save(oaCUser);

                //初始化钱包
                initCUserWallet(date, bigDecimal, id, tag);
            }
            // 登录
            else {
                userOaCUser.setUserToken(null);
                // 设置用户信息
                UserLoginResult userLoginResult = new UserLoginResult();
                addUserOfficeInfo(userOaCUser, userLoginResult);
                tokenUser.setUser(userLoginResult);
                tokenUser.setLoginUserType(ELoginUserType.c);
                tokenUser.setClientId(TokenUtil.getClientId());
                tokenUser.setTokenUserId(userOaCUser.getUserId());

                //生成token
                token = jwtTokenUtil.generateToken(tokenUser);

                // 更新用户token
                QueryWrapper<OaCUser> oaCUserQueryWrapper = new QueryWrapper<>();
                oaCUserQueryWrapper.eq(OaCUser.USER_PHONE, phone).eq(OaCUser.TAG, tag);
                OaCUser oc = new OaCUser();
                oc.setUserToken(token);
                oc.setUpdateTime(date);
                IOaCUserService.update(oc, oaCUserQueryWrapper);
            }
        }
        // 密码登录
        else if (Objects.equals(loginToken.getScope(), OaAuthEnum.passwordType)) {

        }

        return token;
    }

    /**
     * 初始化乘客用户钱包
     *
     * @param date
     * @param bigDecimal
     * @param id
     * @param tag
     */
    private void initCUserWallet(Date date, BigDecimal bigDecimal, Long id, String tag) {
        OaCWallet oaCWallet = new OaCWallet();
        oaCWallet.setWalletId(IDUtil.nextId());
        oaCWallet.setUserId(id);
        oaCWallet.setTag(tag);
        oaCWallet.setCreateUser(id);
        oaCWallet.setCreateTime(date);
        oaCWallet.setUpdateUser(id);
        oaCWallet.setUpdateTime(date);
        oaCWallet.setWalletBalance(bigDecimal);
        oaCWallet.setDeptOfficialBalance(bigDecimal);
        oaCWallet.setPersonalOfficialBalance(bigDecimal);
        oaCWallet.setIsDeptAmount(Integer.valueOf(ParameterEnum.ZERO.getTypeName()));
        oaCWalletMapper.insert(oaCWallet);
    }

    /**
     * 初始化乘客用户钱包
     *
     * @param date
     * @param id
     * @param tag
     */
    private void initDUserWallet(Date date, Long id, String tag) {
        OaDWallet oaDWallet = new OaDWallet();
        oaDWallet.setWalletId(IDUtil.nextId());
        oaDWallet.setDriverId(id);
        oaDWallet.setTag(tag);
        oaDWallet.setCreateUser(id);
        oaDWallet.setCreateTime(date);
        oaDWallet.setUpdateUser(id);
        oaDWallet.setUpdateTime(date);
        oaDWallet.setWalletBalance(BigDecimal.valueOf(0.0));
        oaDWalletMapper.insert(oaDWallet);
    }

    /**
     * 设置用户信息
     *
     * @param oaCUser
     * @param userLoginResult
     */
    private void addUserOfficeInfo(OaCUser oaCUser, UserLoginResult userLoginResult) {
        userLoginResult.setUserId(oaCUser.getUserId());
        userLoginResult.setUserPhone(oaCUser.getUserPhone());
        userLoginResult.setLoginAccount(oaCUser.getLoginAccount());
        userLoginResult.setUserName(oaCUser.getUserName());
        userLoginResult.setNickName(oaCUser.getNickName());
        userLoginResult.setAvatarFileId(oaCUser.getAvatarFileId());
        userLoginResult.setSex(oaCUser.getSex());
        userLoginResult.setEmail(oaCUser.getEmail());
        userLoginResult.setEmailStatus(oaCUser.getEmailStatus());
        userLoginResult.setIsBlocked(oaCUser.getIsBlocked());
        userLoginResult.setIdentityVerfied(oaCUser.getIdentityVerfied());
        userLoginResult.setDriveVerfied(oaCUser.getDriveVerfied());


        Long userId = userLoginResult.getUserId();
        // 获取机构信息
        QueryWrapper<OaCUserOffice> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaCUserOffice.USER_ID, userId);
        OaCUserOffice oaCUserOffice = oaCUserOfficeMapper.selectOne(queryWrapper);
        if (!CheckUtil.objIsEmpty(oaCUserOffice)) {
            userLoginResult.setOfficeId(oaCUserOffice.getOfficeId());
            Long companyId = iOfficeUtilService.getOfficeParentId(oaCUserOffice.getOfficeId());
            userLoginResult.setCompanyId(String.valueOf(companyId));
        }


    }

    /**
     * 司机端用户-登录
     *
     * @param loginToken
     * @return
     */
    @Override
    public Map<String, String> getLoginTokenByD(LoginToken loginToken) {
        String phone = loginToken.getSourceId();
        String credentials = loginToken.getCredentials();
        String tag = TokenUtil.getTag();
        String userType = TokenUtil.getUserType();
        TokenUser tokenUser = new TokenUser();
        Date date = new Date();
        String token = "";
        // 验证验证码是否正确
        checkSmsCode(userType, phone, credentials, tag, whitelistOaDUserPhone);
        // 判断用户是否存在，不存在则注册
        OaDUser userOaDUser = checkDUserExist(phone, tag);
        Map<String, String> map = new HashMap<>(16);
        // 注册用户
        if (CheckUtil.objIsEmpty(userOaDUser)) {
            /*log.info("未发现司机信息，准备注册");
            // 屏蔽注册
            /*throw new PangException(EErrorCode.unRegisterError);
            Long id = IDUtil.nextId();
            log.info("司机ID为：{}",id);
            // 初始化司机个人信息
            OaDUser oaDUser = initOaDTokenUser(phone, tag, tokenUser, date, token, id);
            log.info("司机个人信息：{}", oaDUser.toString());
            //生成token
            token = jwtTokenUtil.generateToken(tokenUser);
            oaDUser.setDriverToken(token);
            IOaDUserService.save(oaDUser);
            // 初始化钱包信息
            initDUserWallet(date, id, tag);
            log.info("钱包信息初始化完成");
            // 速成流程专业版司机完善信息
            this.ImproveDriverInfo(id);
            log.info("信息补充完成");
            // 速成流程专业版添加一辆车
            Long carId = IDUtil.nextId();
            this.addCar(carId, id);
            log.info("车辆添加成功");
            // 速成流程专业版司机绑定车辆
            this.bindCar(id, carId);
            log.info("人车关联成功");*/
            map.put("avatarFile", "");
            map.put("driverName", "");
            map.put("vehNo", "");
            map.put("pushAlias", "");
            map.put("accountStatus", ParameterEnum.ZERO.getTypeName());
        }
        // 登录
        else {
            map.put("accountStatus", ParameterEnum.ONE.getTypeName());
            QueryWrapper<OaDUser> dUserQueryWrapper = new QueryWrapper<>();
            dUserQueryWrapper.eq(OaDUser.DRIVER_PHONE, phone).eq(OaDUser.TAG, tag);
            List<OaDUser> oaDuserList = oaDUserMapper.selectList(dUserQueryWrapper);
            if (!oaDuserList.isEmpty()) {
                // 是否能登录
                if (!oaDuserList.get(0).getAccountStatus().equals(ParameterEnum.ZERO.getType())) {
                    throw PangException.create(EErrorCode.waitApply);
                }
            }
            OaDUserInfo oaDUserInfo = dUserInfoMapper.selectOne(Qw.create().eq(OaDUserInfo.DRIVER_ID, userOaDUser.getDriverId()));
            if (CheckUtil.objIsEmpty(oaDUserInfo)) {
                throw PangException.create(EErrorCode.userInfoError);
            }
            //小于等于 0 代表未添加tid
            if (CheckUtil.objIsEmpty(oaDUserInfo.getTid()) || oaDUserInfo.getTid() <= 0) {
                //未添加Tid.重新设置tid
                int index = 0;
                Long amapTid = 0L;
                while (index < 3) {
                    String Driver = "Driver" + IDUtil.nextId();
                    log.info("AmapTid-" + serviceId + "-" + userOaDUser.getDriverId() + "-" + Driver + "-lhy");
                    amapTid = amapService.getAmapTid(String.valueOf(serviceId), userOaDUser.getDriverId(), Driver, "lhy");
                    if (amapTid != 0) {
                        break;
                    }
                    //停止一秒
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        log.error(e.getMessage());
                        Thread.currentThread().interrupt();
                    }
                    //3次后退出
                    index++;
                }
                if (amapTid == 0) {
                    throw PangException.create(EErrorCode.userInfoError);
                }
                oaDUserInfo.setTid(amapTid);
                int i = dUserInfoMapper.updateById(oaDUserInfo);
                if (i <= 0) {
                    throw PangException.create(EErrorCode.userInfoError);
                }
            }
            userOaDUser.setDriverToken("");
            tokenUser.setUser(userOaDUser);
            tokenUser.setLoginUserType(ELoginUserType.d);
            tokenUser.setClientId(TokenUtil.getClientId());
            tokenUser.setTokenUserId(userOaDUser.getDriverId());
            //生成token
            token = jwtTokenUtil.generateToken(tokenUser);

            // 更新用户token
            QueryWrapper<OaDUser> oaDUserQueryWrapper = new QueryWrapper<>();
            oaDUserQueryWrapper.eq(OaDUser.DRIVER_PHONE, phone).eq(OaDUser.TAG, tag);
            OaDUser od = new OaDUser();
            od.setDriverToken(token);
            od.setUpdateTime(date);
            IOaDUserService.update(od, oaDUserQueryWrapper);
            Map<String, Object> driverInfo = oaDUserMapper.queryDriverDetail(loginToken.getSourceId());
            Rv rv = feignMessageSendService.getFileUrl((Long) driverInfo.get("avatarFile"));
            if (rv.getCode() == EErrorCode.unData.getValue()) {
                map.put("avatarFile", "");
            } else {
                if (CheckUtil.objIsNotEmpty(rv.getData())) {
                    map.put("avatarFile", ((Map) rv.getData()).get("fileUrl").toString());
                } else {
                    map.put("avatarFile", "");
                }
            }
            map.put("driverName", driverInfo.get(OaDUser.DRIVER_NAME).toString());
            if (CheckUtil.objIsNotEmpty(driverInfo.get(OaSysVehicle.VEH_NO))) {
                map.put("vehNo", driverInfo.get(OaSysVehicle.VEH_NO).toString());
            } else {
                map.put("vehNo", "");
            }
            map.put("pushAlias", "Driver" + phone);
        }
        map.put("token", token);
        return map;
    }

    /**
     * 初始化司机个人信息
     *
     * @param phone
     * @param tag
     * @param tokenUser
     * @param date
     * @param token
     * @param id
     * @return
     */
    private OaDUser initOaDTokenUser(String phone, String tag, TokenUser tokenUser, Date date, String token, Long id) {
        OaDUser oaDUser = new OaDUser();
        oaDUser.setDriverPhone(phone);
        oaDUser.setTag(tag);
        oaDUser.setDriverId(id);
        oaDUser.setDriverToken(token);
        oaDUser.setCreateTime(date);
        oaDUser.setCreateUser(id);
        oaDUser.setUpdateTime(date);
        oaDUser.setUpdateUser(id);
        oaDUser.setDriverToken(null);
        tokenUser.setUser(oaDUser);
        tokenUser.setLoginUserType(ELoginUserType.d);
        tokenUser.setClientId(TokenUtil.getClientId());
        return oaDUser;
    }

    /**
     * 管理员登录
     *
     * @param loginToken
     * @return
     */
    @Override
    public String getLoginTokenBySys(LoginToken loginToken) {

        // 验证验证码
        checkLoginVerifCode(loginToken);

        String loginName = loginToken.getSourceId();
        String password = loginToken.getCredentials();
        OaSysUser user = getUser(loginName, password);
        if (CheckUtil.objIsEmpty(user)) {
            throw PangException.create(EErrorCode.unLoginError);
        }
        // 是否能登录
        if (!user.getLoginFlag().equals(ParameterEnum.ONE.getTypeName())) {
            throw PangException.create(EErrorCode.loginErr);
        }
        String token = "";
        // 获取角色
        QueryWrapper<OaSysUserRole> roleQueryWrapper = new QueryWrapper<>();
        roleQueryWrapper.eq(OaSysUserRole.USER_ID, user.getSysUserId());
        List<OaSysUserRole> roleList = oaSysUserRoleMapper.selectList(roleQueryWrapper);
        List<Long> roleIdList = new ArrayList<>();
        List<String> dataScopeList = new ArrayList<>();
        if (!roleList.isEmpty()) {
            for (OaSysUserRole r : roleList) {
                roleIdList.add(r.getRoleId());
            }
        }
        if (!roleIdList.isEmpty()) {
            QueryWrapper<OaSysRole> sysRoleWrapper = new QueryWrapper<>();
            sysRoleWrapper.in(OaSysRole.ROLE_ID, roleIdList);
            List<OaSysRole> sysRoleList = oaSysRoleMapper.selectList(sysRoleWrapper);
            if (!sysRoleList.isEmpty()) {
                for (OaSysRole role : sysRoleList) {
                    dataScopeList.add(role.getDataScope());
                }
            }
        }
        user.setSysUserToken(null);
        TokenUser tokenUser = new TokenUser();
        tokenUser.setUser(user);
        tokenUser.setClientId("CMS");
        tokenUser.setPermissions(new ArrayList<>());
        tokenUser.setRoles(roleIdList);
        tokenUser.setLoginUserType(ELoginUserType.fm);
        tokenUser.setTokenUserId(user.getSysUserId());
        tokenUser.setDataScope(dataScopeList);
        //生成token
        token = jwtTokenUtil.generateToken(tokenUser);
        user.setSysUserToken(token);
        user.setUpdateTime(new Date());
        user.setLoginDate(new Date());
        oaSysUserMapper.updateById(user);

        try {
            // 同步"客服人员"信息给合力
            this.SynchronousHeliUser(user, roleIdList);
        } catch (Exception ex) {
            log.info("同步客服人员用户到合力系统失败！");
        }

        return token;
    }
    /**
     * app后台管理员登录获取用户信息
     *
     * @param loginToken
     * @return
     */
    @Override
    public String getLoginTokenBySys2(LoginToken loginToken) {

        String loginName = loginToken.getSourceId();
        String password = loginToken.getCredentials();
        OaSysUser user = getUser(loginName, password);
        if (CheckUtil.objIsEmpty(user)) {
            throw PangException.create(EErrorCode.unLoginError);
        }
        // 是否能登录
        if (!user.getLoginFlag().equals(ParameterEnum.ONE.getTypeName())) {
            throw PangException.create(EErrorCode.loginErr);
        }
        //获取用户和角色对应的关系
        QueryWrapper<OaSysUserRole> roleQueryWrapper = new QueryWrapper<>();
        roleQueryWrapper.eq(OaSysUserRole.USER_ID, user.getSysUserId());
        List<OaSysUserRole> roleList = oaSysUserRoleMapper.selectList(roleQueryWrapper);
        List<Long> roleIdList = new ArrayList<>();
        List<String> roleNameList = new ArrayList<>();
        if (!roleList.isEmpty()) {
            for (OaSysUserRole r : roleList) {
                roleIdList.add(r.getRoleId());
            }
        }
        if (!roleIdList.isEmpty()) {
            QueryWrapper<OaSysRole> sysRoleWrapper = new QueryWrapper<>();
            sysRoleWrapper.in(OaSysRole.ROLE_ID, roleIdList);
            List<OaSysRole> sysRoleList = oaSysRoleMapper.selectList(sysRoleWrapper);
            if (!sysRoleList.isEmpty()) {
                for (OaSysRole role : sysRoleList) {
                    if(role.getName() != null){
                        roleNameList.add(role.getName());
                    }
                }
            }
        }

        OaSysOffice oaSysOffice = oaSysOfficeMapper.selectById(user.getOfficeId());
        if(CheckUtil.objIsEmpty(oaSysOffice)){
            throw PangException.create(EErrorCode.unOffice);
        }
        JSONObject json = new JSONObject();
        json.put("officeName",oaSysOffice.getName());//机构部门的名字
        json.put("officeAddress",oaSysOffice.getAddress());//城市名字或地址
        json.put("officeGrade",oaSysOffice.getGrade());//机构级别
        json.put("userName",user.getName());//负责人
        json.put("roleName", roleNameList);//角色名字集合
        return json.toString();
    }

    /**
     * 后台登录效验验证码
     *
     * @param loginToken
     */
    private void checkLoginVerifCode(LoginToken loginToken) {

        String code = loginToken.getLoginVerifCode();
        String kaptchaId = loginToken.getKaptchaId();
        if (CheckUtil.strIsEmpty(code, kaptchaId)) {
            throw new PangException(EErrorCode.verifCodeFailError);
        }
        //判断验证码是否还存在
        ValueOperations operations = redisTemplate.opsForValue();
        if (redisTemplate.hasKey(kaptchaId)) {
            if (operations.get(kaptchaId).equals(code)) {
                //验证通过之后删除对应的key
                redisTemplate.delete(kaptchaId);
            } else {
                throw new PangException(EErrorCode.verifCodeError);
            }
        } else {
            throw new PangException(EErrorCode.verifCodeFailError);
        }
    }

    /**
     * 判断用户名和密码是否正确
     *
     * @return
     */
    private OaSysUser getUser(String loginName, String password) {
        // 获取用户的信息
        QueryWrapper<OaSysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysUser.LOGIN_NAME, loginName);
        OaSysUser oaSysUser = oaSysUserMapper.selectOne(queryWrapper);

        // 验证密码
        if (CheckUtil.objIsNotEmpty(oaSysUser)) {
            // MD5加密验证
            Integer salt = oaSysUser.getSalt();
            String pwd = MD5Util.MD5(password + salt).toUpperCase();
            String realPwd = oaSysUser.getPassword();
            if (!Objects.equals(pwd, realPwd)) {
                return null;
            }
        }
        return oaSysUser;
    }

    /**
     * 检查客户端用户是否存在
     *
     * @param phone
     * @param tag
     * @return
     */
    private OaCUser checkCUserExist(String phone, String tag) {
        QueryWrapper<OaCUser> oaCUserQueryWrapper = new QueryWrapper<>();
        oaCUserQueryWrapper.eq(OaCUser.USER_PHONE, phone).eq(OaCUser.TAG, tag);
        OaCUser oaCUser = IOaCUserService.getOne(oaCUserQueryWrapper, true);
        return oaCUser;
    }

    /**
     * 检查司机端用户是否存在
     *
     * @param phone
     * @param tag
     * @return
     */
    private OaDUser checkDUserExist(String phone, String tag) {
        QueryWrapper<OaDUser> oaDUserQueryWrapper = new QueryWrapper<>();
        oaDUserQueryWrapper.eq(OaDUser.DRIVER_PHONE, phone).eq(OaDUser.TAG, tag);
        OaDUser oaDUser = IOaDUserService.getOne(oaDUserQueryWrapper, true);
        return oaDUser;
    }

    /**
     * 效验短信验证码是否正确
     *
     * @param phone
     * @param code
     * @param tag
     * @param whitelist 白名单
     * @return
     */
    @Override
    public void checkSmsCode(String userType, String phone, String code, String tag, String whitelist) {

        // 验证手机号是否是白名单
        String[] phoneList = whitelist.split(",");
        if (!CheckUtil.arrayIsEmpty(phoneList)) {
            for (String p : phoneList) {
                if (Objects.equals(phone, p)) {
                    return;
                }
            }
        }

        // 验证码key
        String smsCodeKey = CommonConstant.REDIS_SMS_LIMIT + "_" + tag + "_" + userType + "_" + phone;
        Date date = new Date();
        log.info("redis中验证码key：" + smsCodeKey, "用户输入验证码：" + code + ",:" + redisTemplate.hasKey(smsCodeKey));
        if (!redisTemplate.hasKey(smsCodeKey)) {
            // 记录错误
            recordSmsErrorCode(userType, phone, tag, smsCodeKey, date);
            throw PangException.create(EErrorCode.verifCodeNotHas);
        }
        log.info("验证码code：" + (String) redisTemplate.opsForValue().get(smsCodeKey));
        if (!Objects.equals(code, (String) redisTemplate.opsForValue().get(smsCodeKey))) {
            recordSmsErrorCode(userType, phone, tag, smsCodeKey, date);
            return;
        }

        redisTemplate.delete(smsCodeKey);
        // 更新验证码已使用
        OaSmsCodeRecord oaSmsCodeRecord = new OaSmsCodeRecord();
        oaSmsCodeRecord.setIsUse(1);
        oaSmsCodeRecord.setUpdateTime(date);

        QueryWrapper<OaSmsCodeRecord> oaSmsCodeRecordQueryWrapper = new QueryWrapper<>();
        oaSmsCodeRecordQueryWrapper.eq(OaSmsCodeRecord.PHONE, phone)
                .eq(OaSmsCodeRecord.TAG, tag)
                .eq(OaSmsCodeRecord.CODE, code);

        iOaSmsCodeRecordService.update(oaSmsCodeRecord, oaSmsCodeRecordQueryWrapper);

    }

    private void recordSmsErrorCode(String userType, String phone, String tag, String smsCodeKey, Date date) {
        // 记录错误
        OaSmsErrorCode oaSmsErrorCode = new OaSmsErrorCode();
        Long id = IDUtil.nextId();
        oaSmsErrorCode.setErrorCodeId(id);
        oaSmsErrorCode.setPhone(phone);
        oaSmsErrorCode.setErrorTime(LocalDate.now());
        oaSmsErrorCode.setTag(tag);
        oaSmsErrorCode.setUserType(ConvertUtil.toInt(userType));
        oaSmsErrorCode.setCreateTime(date);
        oaSmsErrorCode.setCreateUser(id);
        oaSmsErrorCode.setUpdateTime(date);
        oaSmsErrorCode.setUpdateUser(id);
        iOaSmsErrorCodeService.save(oaSmsErrorCode);
        // redisTemplate.delete(smsCodeKey);
        throw PangException.create(EErrorCode.verifCodeError);
    }

    /**
     * 完善司机信息 ( 速成流程专业版 )
     * 仅供测试使用，正式不要用这个
     */
    private void ImproveDriverInfo(Long driverId) {

        Date date = new Date();

        OaDUserInfo oaDUserInfo = new OaDUserInfo();
        oaDUserInfo.setInfoId(IDUtil.nextId());
        oaDUserInfo.setDriverId(driverId);
        oaDUserInfo.setAge(36);
        oaDUserInfo.setNationality(3);
        oaDUserInfo.setDriverLevel("0");
        oaDUserInfo.setBirthday(date);
        oaDUserInfo.setAddress("北京西二旗中关村软件园");
        oaDUserInfo.setEmergencyContact("崔笑健");
        oaDUserInfo.setEmergencyMobile("18434884658");
        oaDUserInfo.setEmergencyAddress("北京西二旗中关村软件园");
        oaDUserInfo.setIdentityPositiveFileId(3696369L);
        oaDUserInfo.setIdentityOtherFileId(3696370L);
        oaDUserInfo.setIdentityDueDate(date);
        oaDUserInfo.setIdentityNumber("123456789456123456");
        oaDUserInfo.setIdentityType(1);
        oaDUserInfo.setIdentityAddress("北京东城区");
        oaDUserInfo.setDriveLicenseFileId(3696371L);
        oaDUserInfo.setDriveOtherLicenseFileId(3696372L);
        oaDUserInfo.setDriveLicenseNo("123456789456123456");
        oaDUserInfo.setDriverStartDate(date);
        oaDUserInfo.setDriveLicenseDuedate(date);
        oaDUserInfo.setDriveLicenseType("123");
        oaDUserInfo.setDriveLicenseIssueplace("北京");
        oaDUserInfo.setPassingDate(date);
        oaDUserInfo.setAuditType(1);
        oaDUserInfo.setRegisterCityId(110000);
        oaDUserInfo.setDriverType(0);
        oaDUserInfo.setAgreement(1);
        oaDUserInfo.setTotalServiceScore(100);
        oaDUserInfo.setBeenDriving(3);
        oaDUserInfo.setOrderQuantityCompleted(0);
        oaDUserInfo.setTag("lhy");
        oaDUserInfo.setCreateTime(date);
        oaDUserInfo.setCreateUser(driverId);
        oaDUserInfo.setUpdateTime(date);
        oaDUserInfo.setUpdateUser(driverId);
        oaDUserInfo.setIsOrder(0);
        oaDUserInfo.setAcceptancOrderStatus(0);
        oaDUserInfo.setTid(1111L);
        oaDUserInfo.setProfessionalQualificationNumber("11111");
        oaDUserInfo.setProfessionalQualificationFileId(123456789L);
        oaDUserInfo.setFirstLoginDate(date);

        oaDUserInfoMapper.insert(oaDUserInfo);

    }

    /**
     * 速成流程专业版添加一辆车
     */
    private void addCar(Long carId, Long id) {

        Date date = new Date();

        OaSysVehicle oaSysVehicle = new OaSysVehicle();

        oaSysVehicle.setVehicleId(carId);
        oaSysVehicle.setVehNo("京AC" + RandomUtil.getRandomSalt());
        oaSysVehicle.setCompanyId(365L);
        oaSysVehicle.setVehStatus(2);
        oaSysVehicle.setVehColor(1);
        oaSysVehicle.setVehSeatsNumber(6);
        oaSysVehicle.setCode("117756");
        oaSysVehicle.setVehicleOwnerId(id);
        oaSysVehicle.setCityCode("130200");
        oaSysVehicle.setVehFuelType(1);

        oaSysVehicle.setTag("lhy");
        oaSysVehicle.setCreateUser(1L);
        oaSysVehicle.setCreateTime(date);
        oaSysVehicle.setUpdateUser(1L);
        oaSysVehicle.setUpdateTime(date);
        oaSysVehicle.setVehType(0);

        oaSysVehicleMapper.insert(oaSysVehicle);

    }

    /**
     * 车辆司机绑定
     */
    private void bindCar(Long driverId, Long carId) {

        Date date = new Date();

        OaDDriverVehicle oaDDriverVehicle = new OaDDriverVehicle();

        oaDDriverVehicle.setLinkedId(IDUtil.nextId());
        oaDDriverVehicle.setDriverId(driverId);
        oaDDriverVehicle.setVehicleId(carId);
        oaDDriverVehicle.setDriverOnlineStatus(0);
        oaDDriverVehicle.setIsUse(1);
        oaDDriverVehicle.setTag("lhy");
        oaDDriverVehicle.setCreateUser(1L);
        oaDDriverVehicle.setCreateTime(date);
        oaDDriverVehicle.setUpdateUser(1L);
        oaDDriverVehicle.setUpdateTime(date);

        oaDDriverVehicleMapper.insert(oaDDriverVehicle);

    }

    /**
     * 司机端用户-登录
     *
     * @param loginToken
     * @return
     */
    @Override
    public String getDetectionToken(DetectionToken loginToken) {
        if (CheckUtil.objIsEmpty(loginToken.getToken())) {
            throw new PangException(EErrorCode.missingArg);
        }
        Map<String, String> map = new HashMap<>(16);
        // 获取用户的信息
        QueryWrapper<OaSysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(OaSysUser.SYS_USER_TOKEN, loginToken.getToken());
        OaSysUser user = oaSysUserMapper.selectOne(queryWrapper);
        if (CheckUtil.objIsEmpty(user)) {
            throw new PangException(EErrorCode.unData);
        }
        return user.getLoginName();
    }

    /**
     * 同步用户信息到合力
     *
     * @param oaSysUser  当前登录用户
     * @param roleIdList 当前登录用户的所有角色
     */
    private void SynchronousHeliUser(OaSysUser oaSysUser, List<Long> roleIdList) {
        if (roleIdList == null
                || roleIdList.size() <= 0) {
            return;
        }

        OaSysRole contractUserRole = this.getRole("客服人员");
        if (contractUserRole == null) {
            log.info("客服人员角色没有找到");
            return;
        }

        if (roleIdList.contains(contractUserRole.getRoleId())) {
            log.info("==========开始：同步客户人员信息给合力===========");

            // 同步用户信息
            LoginSynchronousParam userParam = new LoginSynchronousParam();
            userParam.setLoginId(oaSysUser.getSysUserId().toString());
            userParam.setUserToken(oaSysUser.getSysUserToken());
            userParam.setLoginName(oaSysUser.getLoginName());
            userParam.setStatus("1".equals(oaSysUser.getLoginFlag()) ? "ENABLE" : "DISABLE");
            Rv userSynResult = userToHeLiService.getLoginSynchronous(userParam);
            log.info(String.format("合力用户信息同步结果：{%s}-{%s}", userSynResult.getCode(), userSynResult.getMsg()));

            // 同步角色信息
            RoleSynchronousParam roleParam = new RoleSynchronousParam();
            roleParam.setRoleId(contractUserRole.getRoleId().toString());
            roleParam.setRoleName(contractUserRole.getName());

            //获取角色下用户id列表
            QueryWrapper<OaSysUserRole> roleQueryWrapper = new QueryWrapper<>();
            roleQueryWrapper.eq(OaSysUserRole.ROLE_ID, contractUserRole.getRoleId().toString());
            List<OaSysUserRole> userRoleList = oaSysUserRoleMapper.selectList(roleQueryWrapper);
            List<String> userList = new ArrayList<>();
            if (!userRoleList.isEmpty()) {
                for (OaSysUserRole userRole : userRoleList) {
                    userList.add(String.valueOf(userRole.getUserId()));
                }
            }

            if (userList.size() > 0) {
                roleParam.setLoginId(StringUtils.join(userList.toArray(), "&"));
            }

            Rv roleSynResult = userToHeLiService.getRoleSynchronous(roleParam);
            log.info(String.format("合力角色信息同步结果：{%s}-{%s}", roleSynResult.getCode(), roleSynResult.getMsg()));

            log.info("==========结束：同步客户人员信息给合力===========");
        }

    }

    /**
     * 获取名称获取权限ID
     */
    private OaSysRole getRole(String name) {
        // 查询机构角色关联
        QueryWrapper<OaSysRole> queryWrapper = new QueryWrapper<OaSysRole>();
        queryWrapper.eq(OaSysRole.NAME, name);
        List<OaSysRole> roleList = oaSysRoleMapper.selectList(queryWrapper);

        if (roleList != null
                && roleList.size() > 0) {
            return roleList.get(0);
        } else {
            return null;
        }
    }

    /**
     * 修改乘客端手机号
     *
     * @return
     */
    public Rv modifyUserPhone(String smsCode, String oldTel, String newTel, String tag) {
        checkSmsCode("0", newTel, smsCode, tag, whitelistOaCUserPhone);
        //查询用户基础表
        Long userId = TokenUtil.getTokenUserId();
        List<com.xnyzc.lhy.order.entity.user.UserInfoManage> oaCUserPhone = oaCUserMapper.findOaCUserPhone(newTel, userId);

        OaCUser oaCUser = userMapper.selectById(userId);
        if (oaCUserPhone.size() == 0 && oaCUser != null) {
            //用户基础表
            oaCUser.setUserId(userId);
            oaCUser.setUserPhone(newTel);
            oaCUser.setUpdateTime(new Date());
            oaCUser.setUpdateUser(userId);
            oaCUserMapper.updateById(oaCUser);
            return Rv.wrap(EErrorCode.success);
        } else {
            return Rv.wrap(EErrorCode.dataException.getValue());
        }
    }

    /**
     * 修改乘客端用户信息
     *
     * @return
     */
    public Rv modifyUserInfo(HashMap<String, String> map) {
        String userId = map.get("userId");
        String nickName = map.get("nickName");
        String headUrl = map.get("headUrl");
        String sex = map.get("sex");
        String expand2 = map.get("expand2");

        if (CheckUtil.objIsEmpty(userId, nickName, headUrl, sex, expand2)) {
            return Rv.wrap(EErrorCode.dataException.getValue());
        }
        //查询用户基础表
        OaCUser oaCUser = userMapper.selectById(userId);
        if (oaCUser != null) {
            oaCUser.setUserId(Long.parseLong(userId));
            oaCUser.setNickName(nickName);
            oaCUser.setSex(sex);
            oaCUser.setExpand1(headUrl);//头像url
            oaCUser.setExpand2(expand2);//用户签名
            oaCUser.setUpdateTime(new Date());
            oaCUser.setUpdateUser(Long.parseLong(userId));
            oaCUserMapper.updateById(oaCUser);
            return Rv.wrap(EErrorCode.success);
        } else {
            return Rv.wrap(EErrorCode.dataException.getValue());
        }
    }

    /**
     * 用户实名认证接口
     * //TODO 需要完善该接口  add by jon 2020.4.22
     *
     * @return
     */
    public Rv userRealAuth(HashMap<String, String> map) {
        String uri = "https://bankcard3c.shumaidata.com/bankcard3c";
        String appCode = "6ca376929b77432da527f72008f07a38";
        String key = map.get("key");
        String realname = map.get("realname");
        String idcard = map.get("realname");

        if (CheckUtil.objIsEmpty(key, realname, realname)) {
            return Rv.wrap(EErrorCode.dataException.getValue());
        }

        StringBuilder url = new StringBuilder("?");
        url.append("idcard").append("=").append(idcard).append("&");
        url.append("name").append("=").append(realname).append("&");

        // 最终地址
        String requestUrl = uri + url.toString();
        log.info("请求最终地址为：{}", requestUrl);

        // 构建http
        OkHttpClient client = new OkHttpClient.Builder().build();
        Request request = new Request.Builder().url(requestUrl).addHeader("Authorization", "APPCODE " + appCode).build();

        Response response = null;
        JSONObject jsonResult = null;
        try {

            response = client.newCall(request).execute();
            String result = response.body().string();

            log.info("请求状态：{}，消息：{}", response.code(), response.message());
            log.info("请求结果返回：{}", result);

            jsonResult = JSONObject.parseObject(result);
            return Rv.wrap(EErrorCode.success);
        } catch (IOException e) {
            log.error(e.getMessage());
            throw PangException.create(EErrorCode.gatewayDeny);
        }
    }

    /**
     * 添加司机用户反馈信息
     *
     * @return
     */
    public Rv addFeedBack(HashMap<String, String> map) {
        String userId = map.get("userId");
        String type = map.get("type");//类型（0：用户, 1：司机）
        String content = map.get("content");


        if (CheckUtil.objIsEmpty(userId, type, content)) {
            return Rv.wrap(EErrorCode.dataException.getValue());
        }
        //查询用户基础表
        FeedBack feedBack = new FeedBack();
        try {
            feedBack.setUserId(Long.parseLong(userId));
            feedBack.setType(Short.parseShort(type));
            feedBack.setContent(content);
            feedBack.setIshandle(Short.parseShort("0"));
            feedBack.setAddTime(DateUtil.getCurMilli());
            feedBackMapper.insert(feedBack);
            return Rv.wrap(EErrorCode.success);
        } catch (Exception e) {
            e.printStackTrace();
            throw PangException.create(EErrorCode.gatewayDeny);
        }
    }
}

